home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / boot / netBoot.OpenProm / inet.c < prev    next >
C/C++ Source or Header  |  1991-06-05  |  9KB  |  378 lines

  1. #ifndef lint
  2. static    char sccsid[] = "@(#)inet.c    1.12 88/02/08    Copyr 1986 Sun Micro";
  3. #endif
  4.  
  5. /*
  6.  * Copyright (c) 1986 by Sun Microsystems, Inc.
  7.  */
  8.  
  9. /*
  10.  * Standalone IP send and receive - specific to Ethernet
  11.  * Includes ARP and Reverse ARP
  12.  */
  13. #include "boot.h"
  14. #include "sainet.h"
  15. #include "idprom.h"
  16.  
  17. Net_EtherAddress etherbroadcastaddr = { 
  18.     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  19. };
  20.  
  21.  
  22. #define WAITCNT    2    /* 4 seconds before bitching about arp/revarp */
  23.  
  24. /*
  25.  * Fetch our Ethernet address from the ID prom
  26.  */
  27. myetheraddr(ea)
  28.     Net_EtherAddress *ea;
  29. {
  30.     struct idprom id;
  31.  
  32.     if (idprom(IDFORM_1, &id) != IDFORM_1) {
  33.         printf("ERROR: missing or invalid ID prom\n");
  34.         return;
  35.     }
  36.     *ea = *(Net_EtherAddress *)id.id_ether;
  37. }
  38.  
  39. /*
  40.  * Initialize IP state
  41.  * Find out our Ethernet address and call Reverse ARP
  42.  * to find out our Internet address
  43.  * Set the ARP cache to the broadcast host
  44.  */
  45. inet_init(fileId, sain, tmpbuf)
  46.     register void *fileId;
  47.     register struct sainet *sain;
  48.     char *tmpbuf;
  49. {
  50.     myetheraddr(&sain->myEther);
  51.     bzero((caddr_t)&sain->myAddr, sizeof(Net_InetAddress));
  52.     bzero((caddr_t)&sain->hisAddr, sizeof(Net_InetAddress));
  53.     sain->hisEther = etherbroadcastaddr;
  54.     revarp(fileId, sain, tmpbuf);
  55. }
  56.  
  57.  
  58. /*
  59.  * Output an IP packet
  60.  * Cause ARP to be invoked if necessary
  61.  */
  62. ip_output(fileId, buf, len, sain, tmpbuf)
  63.     register void *fileId;
  64.     caddr_t buf, tmpbuf;
  65.     short len;
  66.     register struct sainet *sain;
  67. {
  68.     register Net_EtherHdr *eh;
  69.     register Net_IPHeader *ip;
  70.  
  71.     eh = (Net_EtherHdr *)buf;
  72.     ip = (Net_IPHeader *)(buf + sizeof(Net_EtherHdr));
  73.     if (!inet_cmp(&ip->dest, &sain->hisAddr)) {
  74.         inet_copy(&sain->hisAddr, &ip->dest);
  75.         arp(fileId, sain, tmpbuf);
  76.     }
  77.     eh->type = NET_ETHER_IP;
  78.     eh->source = sain->myEther;
  79.     eh->destination = sain->hisEther;
  80.     /* checksum the packet */
  81.     ip->checksum = 0;
  82.     ip->checksum = ipcksum((caddr_t)ip, sizeof (Net_IPHeader));
  83.     if (len < NET_ETHER_MIN_BYTES) {
  84.         len = NET_ETHER_MIN_BYTES;
  85.     }
  86.     return !xmit_packet(fileId, buf, len);
  87. }
  88.  
  89. /*
  90.  * Check incoming packets for IP packets
  91.  * addressed to us. Also, respond to ARP packets
  92.  * that wish to know about us.
  93.  * Returns a length for any IP packet addressed to us, 0 otherwise.
  94.  */
  95. ip_input(fileId, buf, sain)
  96.     register void *fileId;
  97.     caddr_t buf;
  98.     register struct sainet *sain;
  99. {
  100.     register short len;
  101.     register Net_EtherHdr *eh;
  102.     register Net_IPHeader *ip;
  103.     register Net_ArpPacket *ea;
  104.  
  105.     len = poll_packet(fileId, buf);
  106.     eh = (Net_EtherHdr *)buf;
  107.     if (eh->type == NET_ETHER_IP &&
  108.         len >= sizeof(Net_EtherHdr)+sizeof(Net_IPHeader)) {
  109.         ip = (Net_IPHeader *)(buf + sizeof(Net_EtherHdr));
  110. #ifdef NOREVARP
  111.         if ((sain->hisAddr.s_addr & 0xFF000000) == 0 &&
  112.             NET_ETHER_COMPARE(etherbroadcastaddr,
  113.             eh->destination) == 0 &&
  114.             (in_broadaddr(sain->hisAddr) ||
  115.             in_lnaof(ip->source) == in_lnaof(sain->hisAddr))) {
  116.             sain->myAddr = ip->dest;
  117.             sain->hisAddr = ip->source;
  118.             sain->hisEther = eh->source;
  119.         }
  120. #endif
  121.         if (!inet_cmp(&ip->dest, &sain->myAddr))
  122.             return (0);
  123.         return (len);
  124.     }
  125.     if (eh->type == NET_ETHER_ARP &&
  126.         len >= sizeof(Net_EtherHdr) + sizeof(Net_ArpPacket)) {
  127.         ea = (Net_ArpPacket *)buf;
  128.         if (ea->protocolType != NET_ETHER_IP)
  129.             return (0);
  130.         if (inet_cmp(ea->senderProtAddr, &sain->hisAddr)) {
  131.             sain->hisEther = ea->senderEtherAddr;
  132.         }
  133.         if (ea->opcode == NET_ARP_REQUEST &&
  134.             inet_cmp(ea->targetProtAddr, &sain->myAddr)) {
  135.             ea->opcode = NET_ARP_REPLY;
  136.             eh->destination = ea->senderEtherAddr;
  137.             eh->source = sain->myEther;
  138.             ea->targetEtherAddr = ea->senderEtherAddr;
  139.             inet_copy(ea->targetProtAddr, ea->senderProtAddr);
  140.             ea->senderEtherAddr = sain->myEther;
  141.             inet_copy(ea->senderProtAddr, &sain->myAddr);
  142.             (void) xmit_packet(fileId, buf, 
  143.                 sizeof(Net_ArpPacket));
  144.         }
  145.         return (0);
  146.     }
  147.     return (0);
  148. }
  149.  
  150. /*
  151.  * arp
  152.  * Broadcasts to determine Ethernet address given IP address
  153.  * See RFC 826
  154.  */
  155. arp(fileId, sain, tmpbuf)
  156.     register void *fileId;
  157.     register struct sainet *sain;
  158.     char *tmpbuf;
  159. {
  160.     Net_ArpPacket out;
  161.  
  162.     if (in_broadaddr(sain->hisAddr)
  163. #ifdef NOREVARP
  164.         || (sain->hisAddr.s_addr & 0xFF000000) == 0
  165. #endif
  166.         ) {
  167.         sain->hisEther = etherbroadcastaddr;
  168.         return;
  169.     }
  170.     out.header.type = NET_ETHER_ARP;
  171.     out.opcode = NET_ARP_REQUEST;
  172.     out.targetEtherAddr = etherbroadcastaddr;    /* what we want */
  173.     inet_copy(out.targetProtAddr, &sain->hisAddr);
  174.     comarp(fileId, sain, &out, tmpbuf);
  175. }
  176.  
  177. /*
  178.  * Reverse ARP client side
  179.  * Determine our Internet address given our Ethernet address
  180.  * See RFC 903
  181.  */
  182. revarp(fileId, sain, tmpbuf)
  183.     register void *fileId;
  184.     register struct sainet *sain;
  185.     char *tmpbuf;
  186. {
  187.     Net_ArpPacket out;
  188.  
  189. #ifdef NOREVARP
  190.     bzero((caddr_t)&sain->myAddr, sizeof(Net_InetAddress));
  191.     bcopy((caddr_t)&sain->myEther.ether_addr_octet[3],
  192.         (caddr_t)(&sain->myAddr)+1, 3);
  193. #else
  194.     out.header.type = NET_ETHER_REVARP;
  195.     out.opcode = NET_RARP_REQUEST;
  196.     out.targetEtherAddr = sain->myEther;
  197.     /* What we want to find out... */
  198.     bzero((caddr_t)out.targetProtAddr, sizeof(Net_InetAddress));
  199.     comarp(fileId, sain, &out, tmpbuf);
  200. #endif
  201. }
  202.  
  203. /*
  204.  * Common ARP code 
  205.  * Broadcast the packet and wait for the right response.
  206.  * Fills in *sain with the results
  207.  */
  208. comarp(fileId, sain, out, tmpbuf)
  209.     register void *fileId;
  210.     register struct sainet *sain;
  211.     register Net_ArpPacket *out;
  212.     char *tmpbuf;
  213. {
  214.     register Net_ArpPacket *in = (Net_ArpPacket *)tmpbuf;
  215.     register int e, count, time, feedback,len, delay = 2;
  216.     char    *ind = "-\\|/";
  217.  
  218.     out->header.destination = etherbroadcastaddr;
  219.     out->header.source = sain->myEther;
  220.     out->hardwareType =  NET_ARP_TYPE_ETHER;
  221.     out->protocolType = NET_ETHER_IP;
  222.     out->hardwareAddrLen = sizeof(Net_EtherAddress);
  223.     out->protocolAddrLen = sizeof(Net_InetAddress);
  224.     out->senderEtherAddr = sain->myEther;
  225.     inet_copy(out->senderProtAddr, &sain->myAddr);
  226.     feedback = 0;
  227.  
  228.     for (count=0; ; count++) {
  229.         if (count == WAITCNT) {
  230.             if (out->opcode == NET_ARP_REQUEST) {
  231.                 printf("\nRequesting Ethernet address for ");
  232.                 inet_print(out->targetProtAddr);
  233.             } else {
  234.                 printf("\nRequesting Internet address for ");
  235.                 ether_print(&out->targetEtherAddr);
  236.             }
  237.         }
  238.         e = xmit_packet(fileId, (caddr_t)out, sizeof *out);
  239.         if (!e)
  240.             printf("X\b");
  241.         else
  242.             printf("%c\b", ind[feedback++ % 4]); /* Show activity */
  243.  
  244.         time = millitime() + (delay * 1000);    /* broadcast delay */
  245.         while (millitime() <= time) {
  246.             len = poll_packet(fileId, tmpbuf);
  247.             if (len < sizeof(Net_ArpPacket))
  248.                 continue;
  249.             if (in->protocolType != NET_ETHER_IP)
  250.                 continue;
  251.             if (out->opcode == NET_ARP_REQUEST) {
  252.                 if (in->header.type != NET_ETHER_ARP)
  253.                     continue;
  254.                 if (in->opcode != NET_ARP_REPLY)
  255.                     continue;
  256.                 if (!inet_cmp(in->senderProtAddr,
  257.                     out->targetProtAddr))
  258.                     continue;
  259.                 if (count >= WAITCNT) {
  260.                     printf("Found at ");
  261.                     ether_print(&in->senderEtherAddr);
  262.                 }
  263.                 sain->hisEther = in->senderEtherAddr;
  264.                 return;
  265.             } else {        /* Reverse ARP */
  266.                 if (in->header.type != NET_ETHER_REVARP)
  267.                     continue;
  268.                 if (in->opcode != NET_RARP_REPLY)
  269.                     continue;
  270.                 if (NET_ETHER_COMPARE(in->targetEtherAddr,
  271.                     out->targetEtherAddr) == 0)
  272.                     continue;
  273.  
  274.                 if (count >= WAITCNT) {
  275.                     printf("Internet address is ");
  276.                     inet_print(in->targetProtAddr);
  277.                 }
  278.                 inet_copy(&sain->myAddr, in->targetProtAddr);
  279.                 /*
  280.                  * short circuit first ARP
  281.                  */
  282.                 inet_copy(&sain->hisAddr, in->senderProtAddr);
  283.                 sain->hisEther = in->senderEtherAddr;
  284.                 return;
  285.             }
  286.         }
  287.  
  288.         delay = delay * 2;    /* Double the request delay */
  289.         if (delay > 64)        /* maximum delay is 64 seconds */
  290.             delay = 64;
  291.  
  292.         reset(fileId);
  293.     }
  294.     /* NOTREACHED */
  295. }
  296.  
  297. /*
  298.  * Return the host portion of an internet address.
  299.  */
  300. in_lnaof(in)
  301.     Net_InetAddress in;
  302. {
  303.     if (NET_INET_CLASS_A_ADDR(in))
  304.         return ((in)&NET_INET_CLASS_A_HOST_MASK);
  305.     else if (NET_INET_CLASS_B_ADDR(in))
  306.         return ((in)&NET_INET_CLASS_B_HOST_MASK);
  307.     else
  308.         return ((in)&NET_INET_CLASS_C_HOST_MASK);
  309. }
  310.  
  311. /*
  312.  * Test for broadcast IP address
  313.  */
  314. in_broadaddr(in)
  315.     Net_InetAddress in;
  316. {
  317.     if (NET_INET_CLASS_A_ADDR(in)) {
  318.         in &= NET_INET_CLASS_A_HOST_MASK;
  319.         return (in == 0 || in == 0xFFFFFF);
  320.     } else if (NET_INET_CLASS_B_ADDR(in)) {
  321.         in &= NET_INET_CLASS_B_HOST_MASK;
  322.         return (in == 0 || in == 0xFFFF);
  323.     } else if (NET_INET_CLASS_C_ADDR(in)) {
  324.         in &= NET_INET_CLASS_C_HOST_MASK;
  325.         return (in == 0 || in == 0xFF);
  326.     } else
  327.         return (0);
  328.     /*NOTREACHED*/
  329. }
  330.  
  331. /*
  332.  * Compute one's complement checksum
  333.  * for IP packet headers 
  334.  */
  335. ipcksum(cp, count)
  336.     caddr_t    cp;
  337.     register unsigned short    count;
  338. {
  339.     register unsigned short    *sp = (unsigned short *)cp;
  340.     register unsigned long    sum = 0;
  341.     register unsigned long    oneword = 0x00010000;
  342.  
  343.     count >>= 1;
  344.     while (count--) {
  345.         sum += *sp++;
  346.         if (sum >= oneword) {        /* Wrap carries into low bit */
  347.             sum -= oneword;
  348.             sum++;
  349.         }
  350.     }
  351.     return (~sum);
  352. }
  353.  
  354. inet_print(p)
  355.     Net_InetAddress *p;
  356. {
  357.     Net_InetAddress s;
  358.  
  359.     inet_copy(&s, p);
  360.     printf("%d.%d.%d.%d\n",
  361.         (s >> 24) & 0xff,
  362.         (s >> 16) & 0xff,
  363.         (s >>  8) & 0xff,
  364.         s & 0xff);
  365. }
  366.  
  367. ether_print(ea)
  368.     Net_EtherAddress *ea;
  369. {
  370.     printf("%x:%x:%x:%x:%x:%x\n",
  371.         NET_ETHER_ADDR_BYTE1(*ea),
  372.         NET_ETHER_ADDR_BYTE2(*ea),
  373.         NET_ETHER_ADDR_BYTE3(*ea),
  374.         NET_ETHER_ADDR_BYTE4(*ea),
  375.         NET_ETHER_ADDR_BYTE5(*ea),
  376.         NET_ETHER_ADDR_BYTE6(*ea));
  377. }
  378.